<html>
<head><meta charset="utf-8"><title>Wanna audit an ipv4 parser? · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html">Wanna audit an ipv4 parser?</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="245745730"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/245745730" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#245745730">(Jul 12 2021 at 20:43)</a>:</h4>
<p>Anyone have a moment to peer-review my ipv4 parser? I ended up writing one after having a minor disagreement with the STD.</p>
<p>In addtition to being correct, it should also be const fn, not slower than std, no panics and no allocs. Swap Ipv4Addr with u32 and it's no std too. Also no unsafe.</p>
<p>Code is admittedly closer to C than idiomatic Rust due to const fn limitations.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="sd">/// Parse [Ipv4Addr] from [core::str]. Each octet must be 1-3 base-10 ascii digits separated by '.' char.</span>
<span class="sd">///</span>
<span class="sd">/// Enabling Strict-mode forbids leading zeros and trailing dot.</span>
<span class="sd">///</span>
<span class="sd">/// IP addresses in non-base-10 formats such as hex or octal are rejected.</span>
<span class="sd">///</span>
<span class="sd">/// Inputs that are parsed successfully in Strict-mode MUST produce identical result when STRICT is false.</span>
<span class="sd">///</span>
<span class="sd">/// License: CC0, Public Domain, etc</span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">parse_ip4</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">STRICT</span>: <span class="kt">bool</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ip</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="n">Ipv4Addr</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MAX_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">15</span><span class="p">;</span><span class="w"> </span><span class="c1">// "255.255.255.255".len()</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MIN_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span><span class="w"> </span><span class="c1">// "0.0.0.0".len()</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">IP_MIN_LEN</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">IP_MAX_LEN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MAX_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">16</span><span class="p">;</span><span class="w"> </span><span class="c1">// "255.255.255.255.".len()</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MIN_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span><span class="w"> </span><span class="c1">// "0.0.0.0".len()</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">IP_MIN_LEN</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">IP_MAX_LEN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">4</span><span class="p">];</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">current_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">char_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">is_previous_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">expect_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">working_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="c1">// Using this temp variable is a lot faster than r[current_octet].</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">();</span><span class="w"></span>

<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ip</span><span class="p">[</span><span class="n">reader</span><span class="p">];</span><span class="w"></span>
<span class="w">        </span><span class="n">reader</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="p">.</span><span class="n">is_ascii_digit</span><span class="p">()</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">STRICT</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="n">expect_dot</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="sc">b'0'</span><span class="p">;</span><span class="w"> </span><span class="c1">// ASCII to u8</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">working_octet</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="c1">// In strict-mode, each leading zero MUST be followed by either '.' char or EOF</span>
<span class="w">                </span><span class="n">expect_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>

<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="n">flag</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">working_octet</span><span class="p">.</span><span class="n">overflowing_mul</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="n">flag</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="n">flag</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">overflowing_add</span><span class="p">(</span><span class="n">u</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="n">flag</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">working_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">v</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">is_previous_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">char_count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">char_count</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="sc">b'.'</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// The address MUST NOT contain two consecutive '.' chars</span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="n">is_previous_dot</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">is_previous_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="p">[</span><span class="n">current_octet</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">working_octet</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">working_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">current_octet</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">char_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">expect_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="c1">// Reset flag</span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="c1">// In Strict-mode, the address MUST NOT contain a trailing '.' char</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">current_octet</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">STRICT</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">())</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">                </span><span class="n">current_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// Byte is neither ASCII number nor '.'</span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">current_octet</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">r</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">working_octet</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nb">None</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">new</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="n">r</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">r</span><span class="p">[</span><span class="mi">3</span><span class="p">]))</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">test_ip4_fast</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// (Input, Strict result, Lax result)</span>
<span class="w">    </span><span class="c1">// When Strict result is some, Lax result can be None to save space.</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">corpus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"000.000.000.000."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Common DNS</span>
<span class="w">        </span><span class="p">(</span><span class="s">"1.1.1.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"8.8.8.8"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"9.9.9.9"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Bad octets</span>
<span class="w">        </span><span class="p">(</span><span class="s">".0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0..0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0..0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0..0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0.."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Signs</span>
<span class="w">        </span><span class="p">(</span><span class="s">"+0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"-0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"+100.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"-100.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Bad stuff</span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.256"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"666.666.666.666"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"5.5.5.5.5"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"3.3.3"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"2.2"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Common LAN IPs</span>
<span class="w">        </span><span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">127</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"192.168.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">192</span><span class="p">,</span><span class="w"> </span><span class="mi">168</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"192.168.1.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">192</span><span class="p">,</span><span class="w"> </span><span class="mi">168</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"172.16.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">172</span><span class="p">,</span><span class="w"> </span><span class="mi">16</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"10.0.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"10.0.1.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Other</span>
<span class="w">        </span><span class="p">(</span><span class="s">"2.4.2.4"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"02.04.02.04"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"002.004.002.004"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"2.4.2.4."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"02.04.02.04."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"002.004.002.004."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"42.42.42.42"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"042.042.042.042"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">])),</span><span class="w"></span>
<span class="w">    </span><span class="p">];</span><span class="w"></span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">sample</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">corpus</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">strict_result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="n">sample</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">lax_result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="n">sample</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sample</span><span class="p">.</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">from</span><span class="p">(</span><span class="n">r</span><span class="p">)));</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="n">lax_result</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sample</span><span class="p">.</span><span class="mi">2</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">lax_result</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">from</span><span class="p">(</span><span class="n">r</span><span class="p">)));</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">lax_result</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">test_ip4_slow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Exhaustive test</span>
<span class="w">    </span><span class="c1">// Tune params to increase/decrease coverage.</span>
<span class="w">    </span><span class="c1">// Use SKIP to speed to dev testing.</span>
<span class="w">    </span><span class="c1">// Use PATTERNs to test differently formatted addresses.</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">MIN</span>: <span class="kt">i16</span> <span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">2</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">MAX</span>: <span class="kt">i16</span> <span class="o">=</span><span class="w"> </span><span class="mi">257</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">SKIP</span>: <span class="kt">i16</span> <span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="cm">/*</span>
<span class="cm">        const MIN: i16 = -666;</span>
<span class="cm">        const MAX: i16 = 1111;</span>
<span class="cm">        const SKIP: i16 = 42;</span>
<span class="cm">    */</span><span class="w"></span>
<span class="w">    </span><span class="cm">/*</span>
<span class="cm">            const STRICT_PATTERN: &amp;str = "{}.{}.{}.{}"; // Strict mode and Lax mode must succeed</span>
<span class="cm">            const LAX_PATTERN: &amp;str = "{:03}.{:03}.{:03}.{:03}."; // Strict mode must return None, but Lax mode must succeed</span>
<span class="cm">            const FAIL_PATTERN: &amp;str = "69.{}.{}.{}.{}."; // Always invalid</span>
<span class="cm">    */</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Use macro magic because const &amp;str is not a string literal</span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">STRICT_PATTERN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="s">"{}.{}.{}.{}"</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">LAX_PATTERN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="s">"{:03}.{:03}.{:03}.{:03}."</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">FAIL_PATTERN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="s">"69.{}.{}.{}.{}"</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="fm">assert!</span><span class="p">(</span><span class="n">SKIP</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">SKIP</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">MAX</span><span class="p">);</span><span class="w"></span>

<span class="w">    </span><span class="c1">// What if we could use 100% of our CPU?</span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">"rayon"</span><span class="cp">)]</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">rayon</span>::<span class="n">prelude</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">"rayon"</span><span class="cp">)]</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">iter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">MIN</span><span class="o">..=</span><span class="n">MAX</span><span class="p">).</span><span class="n">into_par_iter</span><span class="p">();</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[cfg(not(feature = </span><span class="s">"rayon"</span><span class="cp">))]</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">iter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">MIN</span><span class="o">..=</span><span class="n">MAX</span><span class="p">).</span><span class="n">into_iter</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="cm">/*</span>
<span class="cm">    // You probably want cargo.toml with</span>
<span class="cm">    [features]</span>
<span class="cm">    default = ["rayon"]</span>

<span class="cm">    [dependencies]</span>
<span class="cm">    rayon = {version = "1", optional = true }</span>
<span class="cm">    */</span><span class="w"></span>

<span class="w">    </span><span class="n">iter</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span><span class="o">|</span><span class="n">a</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">strict_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="mi">32</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">lax_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="mi">32</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fail_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="mi">32</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fmt</span>::<span class="n">Write</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">FmtWrite</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">strict_ip</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">lax_ip</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">fail_ip</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="fm">write!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">strict_ip</span><span class="p">,</span><span class="w"> </span><span class="n">STRICT_PATTERN</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">strict_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">strict_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span><span class="w"> </span><span class="n">r1</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="fm">write!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">lax_ip</span><span class="p">,</span><span class="w"> </span><span class="n">LAX_PATTERN</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lax_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lax_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r2</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="fm">write!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">fail_ip</span><span class="p">,</span><span class="w"> </span><span class="n">FAIL_PATTERN</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">fail0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">fail_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">fail1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">fail_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">fail0</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">fail1</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r3</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="kd">let</span><span class="w"> </span><span class="n">actual_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">new</span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">));</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span><span class="w"> </span><span class="n">actual_ip</span><span class="p">,</span><span class="w"> </span><span class="s">"IP: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">strict_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r3</span><span class="p">,</span><span class="w"> </span><span class="n">actual_ip</span><span class="p">,</span><span class="w"> </span><span class="s">"IP: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">lax_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="n">d</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">SKIP</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">MAX</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">                </span><span class="n">c</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">SKIP</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">MAX</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">                </span><span class="n">b</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">SKIP</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">MAX</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Progress: {}.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w"></span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">});</span><span class="w"></span>
<span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Done"</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>And if someone wants to turn this into a crate or something, go ahead.</p>



<a name="246147693"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246147693" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Brandon H. Gomes <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246147693">(Jul 15 2021 at 20:00)</a>:</h4>
<p>what is the disagreement between this parser and the std?</p>



<a name="246164140"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246164140" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> XAMPPRocky <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246164140">(Jul 15 2021 at 22:27)</a>:</h4>
<p>std’s parse isn’t <code>const</code>, also it’s strict syntax only.</p>



<a name="246192991"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246192991" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246192991">(Jul 16 2021 at 07:30)</a>:</h4>
<p>I needed a relaxed version that read "001.001.001.001." as "1.1.1.1"</p>
<p>Formatting IP address with zeroes to a  fixed length string for human consumption I find reasonable. For the trailing dot I blame rfc1034 for defining "localhost" == "localhost."</p>



<a name="246194198"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246194198" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jacob Lifshay <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246194198">(Jul 16 2021 at 07:48)</a>:</h4>
<p><span class="user-mention" data-user-id="420380">@Bot+</span> note that the format with leading zeros is ambiguous between interpreting <code>012.034.056.070</code> as <code>12.34.56.70</code> (treating it as decimal) and <code>10.28.46.56</code> (treating the leading zeros as meaning to interpret the numbers as octal, like octal literals in C/C++). That is why IPv4 is generally not written with leading zeros:<br>
<a href="https://superuser.com/questions/929153/leading-zeros-in-ipv4-address-is-that-a-no-no-by-convention-or-standard">https://superuser.com/questions/929153/leading-zeros-in-ipv4-address-is-that-a-no-no-by-convention-or-standard</a></p>



<a name="246194532"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246194532" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246194532">(Jul 16 2021 at 07:53)</a>:</h4>
<p>Small clean up</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">net</span>::<span class="n">Ipv4Addr</span><span class="p">;</span><span class="w"></span>

<span class="sd">/// Parse [Ipv4Addr] from [core::str]. Each octet must be 1-3 base-10 ascii digits separated by '.' char.</span>
<span class="sd">///</span>
<span class="sd">/// Enabling Strict-mode forbids leading zeros and trailing dot.</span>
<span class="sd">///</span>
<span class="sd">/// IP addresses in non-base-10 formats such as hex or octal are rejected.</span>
<span class="sd">///</span>
<span class="sd">/// Inputs that are parsed successfully in Strict-mode MUST produce identical result when STRICT is false.</span>
<span class="sd">///</span>
<span class="sd">/// License: CC0, Public domain, etc</span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">parse_ip4</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="n">STRICT</span>: <span class="kt">bool</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ip</span>: <span class="kp">&amp;</span><span class="kt">str</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nb">Option</span><span class="o">&lt;</span><span class="n">Ipv4Addr</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MAX_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">15</span><span class="p">;</span><span class="w"> </span><span class="c1">// "255.255.255.255".len()</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MIN_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span><span class="w"> </span><span class="c1">// "0.0.0.0".len()</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">IP_MIN_LEN</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">IP_MAX_LEN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MAX_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">16</span><span class="p">;</span><span class="w"> </span><span class="c1">// "255.255.255.255.".len()</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">IP_MIN_LEN</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span><span class="w"> </span><span class="c1">// "0.0.0.0".len()</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">IP_MIN_LEN</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">IP_MAX_LEN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nb">None</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="mi">4</span><span class="p">];</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">current_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">char_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">is_previous_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">expect_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">working_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="k">u8</span><span class="p">;</span><span class="w"> </span><span class="c1">// Using this temp variable instead of r[current_octet] cuts time by one fifth.</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ip</span><span class="p">.</span><span class="n">as_bytes</span><span class="p">();</span><span class="w"></span>

<span class="w">    </span><span class="c1">// In non-strict mode, strip the trailing dot if it is present.</span>
<span class="w">    </span><span class="c1">// if STRICT || ip.last() != Some(b'.')</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">reader_max</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">ip</span><span class="p">[</span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="sc">b'.'</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">ip</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="w"></span>
<span class="w">    </span><span class="p">};</span><span class="w"></span>

<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="n">reader</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">reader_max</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ip</span><span class="p">[</span><span class="n">reader</span><span class="p">];</span><span class="w"></span>
<span class="w">        </span><span class="n">reader</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="p">.</span><span class="n">is_ascii_digit</span><span class="p">()</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">STRICT</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="n">expect_dot</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="sc">b'0'</span><span class="p">;</span><span class="w"> </span><span class="c1">// ASCII to u8</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">working_octet</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="c1">// In strict-mode, each leading zero MUST be followed by either '.' char or EOF</span>
<span class="w">                </span><span class="n">expect_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>

<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="n">flag</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">working_octet</span><span class="p">.</span><span class="n">overflowing_mul</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="n">flag</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">v</span><span class="p">,</span><span class="w"> </span><span class="n">flag</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">overflowing_add</span><span class="p">(</span><span class="n">u</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="n">flag</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">working_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">v</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">is_previous_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">char_count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">char_count</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="sc">b'.'</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// The address MUST NOT contain two consecutive '.' chars</span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">|=</span><span class="w"> </span><span class="n">is_previous_dot</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">is_previous_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">r</span><span class="p">[</span><span class="n">current_octet</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">working_octet</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">working_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">current_octet</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="n">char_count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">STRICT</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">expect_dot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span><span class="w"> </span><span class="c1">// Reset flag</span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">current_octet</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">                </span><span class="n">current_octet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="c1">// Byte is neither ASCII number nor '.'</span>
<span class="w">            </span><span class="n">fail</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="n">r</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">working_octet</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="n">fail</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">new</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">r</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="n">r</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">r</span><span class="p">[</span><span class="mi">3</span><span class="p">]))</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nb">None</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">test_ip4_fast</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// (Input, Strict result, Lax result)</span>
<span class="w">    </span><span class="c1">// When Strict result is some, Lax result can be None to save space.</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">corpus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"000.000.000.000."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Common DNS</span>
<span class="w">        </span><span class="p">(</span><span class="s">"1.1.1.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"8.8.8.8"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"9.9.9.9"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Bad octets</span>
<span class="w">        </span><span class="p">(</span><span class="s">".0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0..0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0..0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0..0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">0</span><span class="k">u8</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0.."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"......."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"10101010"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"01010101"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Signs</span>
<span class="w">        </span><span class="p">(</span><span class="s">"+0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"-0.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"+100.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"-100.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Bad stuff</span>
<span class="w">        </span><span class="p">(</span><span class="s">"0.0.0.256"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"666.666.666.666"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"5.5.5.5.5"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"3.3.3"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"2.2"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Common LAN IPs</span>
<span class="w">        </span><span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">127</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"192.168.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">192</span><span class="p">,</span><span class="w"> </span><span class="mi">168</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"192.168.1.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">192</span><span class="p">,</span><span class="w"> </span><span class="mi">168</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"172.16.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">172</span><span class="p">,</span><span class="w"> </span><span class="mi">16</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"10.0.0.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"10.0.1.1"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">10</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="c1">// Other</span>
<span class="w">        </span><span class="p">(</span><span class="s">"2.4.2.4"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"02.04.02.04"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"002.004.002.004"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"2.4.2.4."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"02.04.02.04."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"002.004.002.004."</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">])),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"42.42.42.42"</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">]),</span><span class="w"> </span><span class="nb">None</span><span class="p">),</span><span class="w"></span>
<span class="w">        </span><span class="p">(</span><span class="s">"042.042.042.042"</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">([</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">42</span><span class="p">])),</span><span class="w"></span>
<span class="w">    </span><span class="p">];</span><span class="w"></span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">sample</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">corpus</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">strict_result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="n">sample</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">lax_result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="n">sample</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">std</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Ipv4Addr</span>::<span class="n">from_str</span><span class="p">(</span><span class="n">sample</span><span class="p">.</span><span class="mi">0</span><span class="p">).</span><span class="n">ok</span><span class="p">();</span><span class="w"></span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="n">std</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">strict_result</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">println!</span><span class="p">(</span><span class="s">"{:?}, {:?}, {}"</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="p">,</span><span class="w"> </span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="n">sample</span><span class="p">.</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sample</span><span class="p">.</span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">from</span><span class="p">(</span><span class="n">r</span><span class="p">)));</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="n">lax_result</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sample</span><span class="p">.</span><span class="mi">2</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">lax_result</span><span class="p">,</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">from</span><span class="p">(</span><span class="n">r</span><span class="p">)));</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">strict_result</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">lax_result</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">fn</span> <span class="nf">test_ip4_slow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Exhaustive test</span>
<span class="w">    </span><span class="c1">// Tune params to increase/decrease coverage.</span>
<span class="w">    </span><span class="c1">// Use SKIP to speed to dev testing.</span>
<span class="w">    </span><span class="c1">// Use PATTERNs to test differently formatted addresses.</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">MIN</span>: <span class="kt">i16</span> <span class="o">=</span><span class="w"> </span><span class="o">-</span><span class="mi">2</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">MAX</span>: <span class="kt">i16</span> <span class="o">=</span><span class="w"> </span><span class="mi">257</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">SKIP</span>: <span class="kt">i16</span> <span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="cm">/*</span>
<span class="cm">        const MIN: i16 = -666;</span>
<span class="cm">        const MAX: i16 = 1111;</span>
<span class="cm">        const SKIP: i16 = 42;</span>
<span class="cm">    */</span><span class="w"></span>
<span class="w">    </span><span class="cm">/*</span>
<span class="cm">            const STRICT_PATTERN: &amp;str = "{}.{}.{}.{}"; // Strict mode and Lax mode must succeed</span>
<span class="cm">            const LAX_PATTERN: &amp;str = "{:03}.{:03}.{:03}.{:03}."; // Strict mode must return None, but Lax mode must succeed</span>
<span class="cm">            const FAIL_PATTERN: &amp;str = "69.{}.{}.{}.{}."; // Always invalid</span>
<span class="cm">    */</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Use macro magic because const &amp;str is not a string literal</span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">STRICT_PATTERN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="s">"{}.{}.{}.{}"</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">LAX_PATTERN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="s">"{:03}.{:03}.{:03}.{:03}."</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">FAIL_PATTERN</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="s">"+{}.{}.{}.{}."</span><span class="w"></span>
<span class="w">        </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="fm">assert!</span><span class="p">(</span><span class="n">SKIP</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">SKIP</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">MAX</span><span class="p">);</span><span class="w"></span>

<span class="w">    </span><span class="c1">// What if we could use 100% of our CPU?</span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">"rayon"</span><span class="cp">)]</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">rayon</span>::<span class="n">prelude</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="cp">#[cfg(feature = </span><span class="s">"rayon"</span><span class="cp">)]</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">iter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">MIN</span><span class="o">..=</span><span class="n">MAX</span><span class="p">).</span><span class="n">into_par_iter</span><span class="p">();</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[cfg(not(feature = </span><span class="s">"rayon"</span><span class="cp">))]</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">iter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">MIN</span><span class="o">..=</span><span class="n">MAX</span><span class="p">).</span><span class="n">into_iter</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="cm">/*</span>
<span class="cm">    // You really want a cargo.toml with</span>
<span class="cm">    [features]</span>
<span class="cm">    default = ["rayon"]</span>

<span class="cm">    [dependencies]</span>
<span class="cm">    rayon = {version = "1", optional = true }</span>
<span class="cm">    */</span><span class="w"></span>

<span class="w">    </span><span class="n">iter</span><span class="p">.</span><span class="n">for_each</span><span class="p">(</span><span class="o">|</span><span class="n">a</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>

<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">strict_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="mi">32</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">lax_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="mi">32</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">fail_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">with_capacity</span><span class="p">(</span><span class="mi">32</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="n">fmt</span>::<span class="n">Write</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">FmtWrite</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="k">loop</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="n">strict_ip</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">lax_ip</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="n">fail_ip</span><span class="p">.</span><span class="n">truncate</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="fm">write!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">strict_ip</span><span class="p">,</span><span class="w"> </span><span class="n">STRICT_PATTERN</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">strict_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">strict_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span><span class="w"> </span><span class="n">r1</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="fm">write!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">lax_ip</span><span class="p">,</span><span class="w"> </span><span class="n">LAX_PATTERN</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lax_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">r3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lax_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r2</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="fm">write!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">fail_ip</span><span class="p">,</span><span class="w"> </span><span class="n">FAIL_PATTERN</span><span class="o">!</span><span class="p">(),</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">fail0</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">fail_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="kd">let</span><span class="w"> </span><span class="n">fail1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">false</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">fail_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">fail0</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">fail1</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">255</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r3</span><span class="p">,</span><span class="w"> </span><span class="nb">None</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="kd">let</span><span class="w"> </span><span class="n">actual_ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Ipv4Addr</span>::<span class="n">new</span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">,</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">u8</span><span class="p">));</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r0</span><span class="p">,</span><span class="w"> </span><span class="n">actual_ip</span><span class="p">,</span><span class="w"> </span><span class="s">"IP: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">strict_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">                </span><span class="fm">assert_eq!</span><span class="p">(</span><span class="n">r3</span><span class="p">,</span><span class="w"> </span><span class="n">actual_ip</span><span class="p">,</span><span class="w"> </span><span class="s">"IP: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">lax_ip</span><span class="p">);</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="n">d</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">SKIP</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">MAX</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">                </span><span class="n">c</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">SKIP</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">MAX</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MIN</span><span class="p">;</span><span class="w"></span>
<span class="w">                </span><span class="n">b</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">SKIP</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">MAX</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Progress: {}.0.0.0"</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span><span class="w"></span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="p">});</span><span class="w"></span>
<span class="w">    </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Done"</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="246194608"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246194608" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246194608">(Jul 16 2021 at 07:54)</a>:</h4>
<p>And benches!</p>
<div class="codehilite"><pre><span></span><code>test tests::bench_new_max   ... bench:          17 ns/iter (+/- 0)
test tests::bench_new_min   ... bench:           8 ns/iter (+/- 0)
test tests::bench_new_nines ... bench:           9 ns/iter (+/- 0)
test tests::bench_std_max   ... bench:          21 ns/iter (+/- 0)
test tests::bench_std_min   ... bench:          13 ns/iter (+/- 0)
test tests::bench_std_nines ... bench:          13 ns/iter (+/- 0)
</code></pre></div>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#![feature(test)]</span><span class="w"></span>

<span class="cp">#[cfg(test)]</span><span class="w"></span>
<span class="k">mod</span> <span class="nn">tests</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">extern</span><span class="w"> </span><span class="k">crate</span><span class="w"> </span><span class="n">test</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="kt">str</span>::<span class="n">FromStr</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="k">super</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="k">use</span><span class="w"> </span><span class="n">test</span>::<span class="n">Bencher</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[bench]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">bench_new_max</span><span class="p">(</span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">test</span>::<span class="n">black_box</span><span class="p">(</span><span class="s">"255.255.255.255"</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ip</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[bench]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">bench_std_max</span><span class="p">(</span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">test</span>::<span class="n">black_box</span><span class="p">(</span><span class="s">"255.255.255.255"</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">Ipv4Addr</span>::<span class="n">from_str</span><span class="p">(</span><span class="n">ip</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[bench]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">bench_new_min</span><span class="p">(</span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">test</span>::<span class="n">black_box</span><span class="p">(</span><span class="s">"0.0.0.0"</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ip</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[bench]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">bench_std_min</span><span class="p">(</span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">test</span>::<span class="n">black_box</span><span class="p">(</span><span class="s">"0.0.0.0"</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">Ipv4Addr</span>::<span class="n">from_str</span><span class="p">(</span><span class="n">ip</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[bench]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">bench_new_nines</span><span class="p">(</span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">test</span>::<span class="n">black_box</span><span class="p">(</span><span class="s">"9.9.9.9"</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">parse_ip4</span>::<span class="o">&lt;</span><span class="kc">true</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ip</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="cp">#[bench]</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">bench_std_nines</span><span class="p">(</span><span class="n">b</span>: <span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">test</span>::<span class="n">black_box</span><span class="p">(</span><span class="s">"9.9.9.9"</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">Ipv4Addr</span>::<span class="n">from_str</span><span class="p">(</span><span class="n">ip</span><span class="p">));</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="246396486"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246396486" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246396486">(Jul 18 2021 at 20:24)</a>:</h4>
<p><span class="user-mention silent" data-user-id="229517">Jacob Lifshay</span> <a href="#narrow/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F/near/246194198">said</a>:</p>
<blockquote>
<p>treating the leading zeros as meaning to interpret the numbers as octal</p>
</blockquote>
<p>Yeah, octal IPs should have never happened. IIRC blame goes to Unix? As my use case is about humans with a liking to fixed length formats and who have never heard of octal, leading zeros are fine.</p>



<a name="246396505"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246396505" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246396505">(Jul 18 2021 at 20:24)</a>:</h4>
<p>This weekend I'm wasting time to hack together a const ipv6 parser.</p>
<p>Progress is promising, with micro benches running up to three times faster.</p>
<p>Note: input = "::1"<br>
test tests::bench_ipv6_loopback_new    ... bench:           8 ns/iter (+/- 0)<br>
test tests::bench_ipv6_loopback_std    ... bench:          34 ns/iter (+/- 0)</p>
<p>Note: input = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"<br>
test tests::bench_ipv6_max_new         ... bench:          82 ns/iter (+/- 0)<br>
test tests::bench_ipv6_max_std         ... bench:         108 ns/iter (+/- 0)</p>
<p>No code yet because the parser sometimes accepts zero octets incorrectly.</p>
<p>Working around lack of const_fn_transmute was fun.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="sd">/// A safe and const [`core::mem::transmute::&lt;[u16; 8], u128&gt;(n)`](core::mem::transmute)</span>
<span class="cp">#[inline(always)]</span><span class="w"></span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">u16x8_to_u128</span><span class="p">(</span><span class="n">n</span>: <span class="p">[</span><span class="kt">u16</span><span class="p">;</span><span class="w"> </span><span class="mi">8</span><span class="p">])</span><span class="w"> </span>-&gt; <span class="kt">u128</span> <span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// How's this for idiotic safe rust?</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b1</span><span class="p">,</span><span class="w"> </span><span class="n">b2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b3</span><span class="p">,</span><span class="w"> </span><span class="n">b4</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b5</span><span class="p">,</span><span class="w"> </span><span class="n">b6</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b7</span><span class="p">,</span><span class="w"> </span><span class="n">b8</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">3</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b9</span><span class="p">,</span><span class="w"> </span><span class="n">b10</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">4</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b11</span><span class="p">,</span><span class="w"> </span><span class="n">b12</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">5</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b13</span><span class="p">,</span><span class="w"> </span><span class="n">b14</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">6</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b15</span><span class="p">,</span><span class="w"> </span><span class="n">b16</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">7</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kt">u128</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="w"></span>
<span class="w">        </span><span class="n">b1</span><span class="p">,</span><span class="w"> </span><span class="n">b2</span><span class="p">,</span><span class="w"> </span><span class="n">b3</span><span class="p">,</span><span class="w"> </span><span class="n">b4</span><span class="p">,</span><span class="w"> </span><span class="n">b5</span><span class="p">,</span><span class="w"> </span><span class="n">b6</span><span class="p">,</span><span class="w"> </span><span class="n">b7</span><span class="p">,</span><span class="w"> </span><span class="n">b8</span><span class="p">,</span><span class="w"> </span><span class="n">b9</span><span class="p">,</span><span class="w"> </span><span class="n">b10</span><span class="p">,</span><span class="w"> </span><span class="n">b11</span><span class="p">,</span><span class="w"> </span><span class="n">b12</span><span class="p">,</span><span class="w"> </span><span class="n">b13</span><span class="p">,</span><span class="w"> </span><span class="n">b14</span><span class="p">,</span><span class="w"> </span><span class="n">b15</span><span class="p">,</span><span class="w"> </span><span class="n">b16</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">])</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="sd">/// A safe and const [`core::mem::transmute::&lt;u128, [u16; 8]&gt;(n)`](core::mem::transmute)</span>
<span class="cp">#[inline(always)]</span><span class="w"></span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">u128_to_u16x8</span><span class="p">(</span><span class="n">n</span>: <span class="kt">u128</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="p">[</span><span class="kt">u16</span><span class="p">;</span><span class="w"> </span><span class="mi">8</span><span class="p">]</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b1</span><span class="p">,</span><span class="w"> </span><span class="n">b2</span><span class="p">,</span><span class="w"> </span><span class="n">b3</span><span class="p">,</span><span class="w"> </span><span class="n">b4</span><span class="p">,</span><span class="w"> </span><span class="n">b5</span><span class="p">,</span><span class="w"> </span><span class="n">b6</span><span class="p">,</span><span class="w"> </span><span class="n">b7</span><span class="p">,</span><span class="w"> </span><span class="n">b8</span><span class="p">,</span><span class="w"> </span><span class="n">b9</span><span class="p">,</span><span class="w"> </span><span class="n">b10</span><span class="p">,</span><span class="w"> </span><span class="n">b11</span><span class="p">,</span><span class="w"> </span><span class="n">b12</span><span class="p">,</span><span class="w"> </span><span class="n">b13</span><span class="p">,</span><span class="w"> </span><span class="n">b14</span><span class="p">,</span><span class="w"> </span><span class="n">b15</span><span class="p">,</span><span class="w"> </span><span class="n">b16</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">.</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="p">[</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b1</span><span class="p">,</span><span class="w"> </span><span class="n">b2</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b3</span><span class="p">,</span><span class="w"> </span><span class="n">b4</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b5</span><span class="p">,</span><span class="w"> </span><span class="n">b6</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b7</span><span class="p">,</span><span class="w"> </span><span class="n">b8</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b9</span><span class="p">,</span><span class="w"> </span><span class="n">b10</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b11</span><span class="p">,</span><span class="w"> </span><span class="n">b12</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b13</span><span class="p">,</span><span class="w"> </span><span class="n">b14</span><span class="p">]),</span><span class="w"></span>
<span class="w">        </span><span class="kt">u16</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="n">b15</span><span class="p">,</span><span class="w"> </span><span class="n">b16</span><span class="p">]),</span><span class="w"></span>
<span class="w">    </span><span class="p">]</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="246397110"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/246397110" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jacob Lifshay <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#246397110">(Jul 18 2021 at 20:40)</a>:</h4>
<p><span class="user-mention silent" data-user-id="420380">Bot+</span> <a href="#narrow/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F/near/246396505">said</a>:</p>
<blockquote>
<p><div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="sd">/// A safe and const [`core::mem::transmute::&lt;[u16; 8], u128&gt;(n)`](core::mem::transmute)</span>
<span class="cp">#[inline(always)]</span><span class="w"></span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">u16x8_to_u128</span><span class="p">(</span><span class="n">n</span>: <span class="p">[</span><span class="kt">u16</span><span class="p">;</span><span class="w"> </span><span class="mi">8</span><span class="p">])</span><span class="w"> </span>-&gt; <span class="kt">u128</span> <span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// How's this for idiotic safe rust?</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b1</span><span class="p">,</span><span class="w"> </span><span class="n">b2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b3</span><span class="p">,</span><span class="w"> </span><span class="n">b4</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b5</span><span class="p">,</span><span class="w"> </span><span class="n">b6</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b7</span><span class="p">,</span><span class="w"> </span><span class="n">b8</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">3</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b9</span><span class="p">,</span><span class="w"> </span><span class="n">b10</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">4</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b11</span><span class="p">,</span><span class="w"> </span><span class="n">b12</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">5</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b13</span><span class="p">,</span><span class="w"> </span><span class="n">b14</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">6</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">[</span><span class="n">b15</span><span class="p">,</span><span class="w"> </span><span class="n">b16</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">n</span><span class="p">[</span><span class="mi">7</span><span class="p">].</span><span class="n">to_le_bytes</span><span class="p">();</span><span class="w"></span>
<span class="w">    </span><span class="kt">u128</span>::<span class="n">from_le_bytes</span><span class="p">([</span><span class="w"></span>
<span class="w">        </span><span class="n">b1</span><span class="p">,</span><span class="w"> </span><span class="n">b2</span><span class="p">,</span><span class="w"> </span><span class="n">b3</span><span class="p">,</span><span class="w"> </span><span class="n">b4</span><span class="p">,</span><span class="w"> </span><span class="n">b5</span><span class="p">,</span><span class="w"> </span><span class="n">b6</span><span class="p">,</span><span class="w"> </span><span class="n">b7</span><span class="p">,</span><span class="w"> </span><span class="n">b8</span><span class="p">,</span><span class="w"> </span><span class="n">b9</span><span class="p">,</span><span class="w"> </span><span class="n">b10</span><span class="p">,</span><span class="w"> </span><span class="n">b11</span><span class="p">,</span><span class="w"> </span><span class="n">b12</span><span class="p">,</span><span class="w"> </span><span class="n">b13</span><span class="p">,</span><span class="w"> </span><span class="n">b14</span><span class="p">,</span><span class="w"> </span><span class="n">b15</span><span class="p">,</span><span class="w"> </span><span class="n">b16</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">])</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div><br>
</p>
</blockquote>
<p>well, assuming you want your code to do give the same values on big-endian architectures, you'd still need the above code. <code>transmute</code> would only work if the above code instead used <code>from_ne_bytes</code> and <code>to_ne_bytes</code>.</p>



<a name="247705992"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Wanna%20audit%20an%20ipv4%20parser%3F/near/247705992" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Bot+ <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Wanna.20audit.20an.20ipv4.20parser.3F.html#247705992">(Jul 30 2021 at 13:15)</a>:</h4>
<p>Major update with ipv6 and ports:</p>
<p><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=995d99bac1bd2266710c7469c602aad1">https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=995d99bac1bd2266710c7469c602aad1</a></p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">ip4_and_p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">std</span>::<span class="n">net</span>::<span class="n">IpAddr</span>::<span class="n">V4</span><span class="p">(</span><span class="n">std</span>::<span class="n">net</span>::<span class="n">Ipv4Addr</span>::<span class="n">new</span><span class="p">(</span><span class="mi">127</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)),</span><span class="w"> </span><span class="mi">443</span><span class="p">);</span><span class="w"></span>
<span class="fm">assert_eq!</span><span class="p">(</span><span class="n">parse_ip_and_port</span><span class="p">(</span><span class="s">"127.0.0.1:443"</span><span class="p">,</span><span class="w"> </span><span class="mi">80</span><span class="p">),</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">ip4_and_p</span><span class="p">));</span><span class="w"></span>

<span class="kd">let</span><span class="w"> </span><span class="n">ip6_and_p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">std</span>::<span class="n">net</span>::<span class="n">IpAddr</span>::<span class="n">V6</span><span class="p">(</span><span class="n">std</span>::<span class="n">net</span>::<span class="n">Ipv6Addr</span>::<span class="n">new</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">,</span><span class="mi">0</span><span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)),</span><span class="w"> </span><span class="mi">443</span><span class="p">);</span><span class="w"></span>
<span class="fm">assert_eq!</span><span class="p">(</span><span class="n">parse_ip_and_port</span><span class="p">(</span><span class="s">"[::1]:443"</span><span class="p">,</span><span class="w"> </span><span class="mi">80</span><span class="p">),</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">ip6_and_p</span><span class="p">));</span><span class="w"></span>
</code></pre></div>
<p>Tests pass with Miri (both little endian and emulated big endian)</p>
<p>Valid inputs seem fine. Invalid inputs look also fine so far, but more fuzzing is needed.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>